package pro.lepers.portfolio.view {
	import pro.lepers.portfolio.Consts;
	import pro.lepers.portfolio.core.master;
	import pro.lepers.portfolio.event.MasterModelEvent;
	import pro.lepers.portfolio.event.RenderEvent;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	/**
	 * @author plepers
	 */
	public class ScaledContainer extends Sprite {
		

		public function ScaledContainer () {
			_build();
			addEventListener( Event.ADDED_TO_STAGE, onAdded );
			addEventListener( Event.REMOVED_FROM_STAGE, onRemoved );
		}
		
		
		public function setSize ( w : int, h : int ) : void {
			
			_h = h;
			_w = w;
		}

		private function _build () : void {
			_raster = new Bitmap();
			_smallRaster = new Bitmap();
			//addChild( _raster );
			
			container = new Sprite();
			addChild( container );
		}

		private function onAdded( e : Event ) : void {
			master.addEventListener( MasterModelEvent.DOWN_SCALE, onScaleStart, false, -Infinity );
			master.addEventListener( MasterModelEvent.UP_SCALE, onScaleStart, false, -Infinity );
			master.addEventListener( MasterModelEvent.SCALE_STOP, onScaleStop );
			master.addEventListener( MasterModelEvent.SCALE_CHANGE, onScaleChange );
			master.addEventListener( MasterModelEvent.DOWN_SCALED, onDownScaled);
			master.addEventListener( MasterModelEvent.UP_SCALED, onUpScaled );
		}

		private function onRemoved( e : Event ) : void {
			master.removeEventListener( MasterModelEvent.DOWN_SCALE, onScaleStart );
			master.removeEventListener( MasterModelEvent.UP_SCALE, onScaleStart );
			master.removeEventListener( MasterModelEvent.SCALE_STOP, onScaleStop );
			master.removeEventListener( MasterModelEvent.SCALE_CHANGE, onScaleChange );
			master.removeEventListener( MasterModelEvent.DOWN_SCALED, onDownScaled );
			master.removeEventListener( MasterModelEvent.UP_SCALED, onUpScaled );
		}

		private function onScaleChange (event : MasterModelEvent) : void {
			var dsc : Number = (1 - master.globalScale / Consts.SCALE_FX);
			var dscc : Number =- master.globalScale +1;
			
			_raster.x = (_w / 2) * dsc;
			_raster.y = (_h / 2) * dsc;
			
			_raster.scaleX = _raster.scaleY = master.globalScale;

			container.x = (_w / 2) * dscc;
			container.y = (_h / 2) * dscc;
//			
			container.scaleX = container.scaleY = master.globalScale;
			var luminance : Number = master.scaleProgress * 0.7 + ( 1-.7 );
			_raster.transform.colorTransform = new ColorTransform( luminance,luminance,luminance );
		}

		private function onScaleStart (event : MasterModelEvent) : void {
			handleRedraw( false );

			disposeSmallRaster();
			
			_raster.filters = [ ];
			//_raster.smoothing = false;

			_rasterize();
			onScaleChange( null );
			
			addChild( _raster );
			if( container.parent )
				removeChild( container );
			if( _smallRaster.parent )
				removeChild( _smallRaster );
		}

		
		private function onDownScaled (event : MasterModelEvent) : void {
			
			if( _raster.parent )
				removeChild( _raster );
			
			_smallRasterize();
			addChild( _smallRaster );
			
			handleRedraw( true );
//			_raster.scaleX = _raster.scaleY = 1;
//			_raster.filters = [ new BlurFilter(2,2,2) ];
//			_raster.smoothing = true;
		}

		private function onUpScaled (event : MasterModelEvent) : void {
			removeChild( _raster );
			addChild( container );
			
			disposeRaster();
//			
			var dsc : Number = - master.globalScale +1;
			container.x = (_w / 2) * dsc;
			container.y = (_h / 2) * dsc;
			container.scaleX = container.scaleY = master.globalScale;
			
		}


		private function onScaleStop (event : MasterModelEvent) : void {
			
		}

		private function _rasterize () : void {
			disposeRaster();
				
			var invScale : Number = 1 / Consts.SCALE_FX;


			var transMatrix : Matrix = new Matrix( );
			transMatrix.translate(- _w * ( 1 - invScale ) / 2,- _h * ( 1 - invScale ) / 2 );	

			_raster.bitmapData = new BitmapData( _w * invScale, _h * invScale, false );
			_raster.bitmapData.draw( container, transMatrix );
		}

		private function _smallRasterize () : void {
			disposeSmallRaster();
			
			_smallRaster.bitmapData = new BitmapData( _w, _h );
			
			var scaleMatrix : Matrix = new Matrix( );
			scaleMatrix.scale( Consts.SCALE_FX, Consts.SCALE_FX );	
			
			_smallRaster.bitmapData.draw( _raster.bitmapData, scaleMatrix, _raster.transform.colorTransform, null, null, false );
			_smallRaster.bitmapData.applyFilter(_smallRaster.bitmapData, _smallRaster.bitmapData.rect, new Point(), new BlurFilter( 2,2,2 ) );
		}

		private function disposeRaster () : void {
			if( _raster.bitmapData )
				_raster.bitmapData.dispose( );
			_raster.bitmapData = null;
		
		}

		private function disposeSmallRaster () : void {
			if( _smallRaster.bitmapData )
				_smallRaster.bitmapData.dispose( );
			_smallRaster.bitmapData = null;
		}

		
		
		private var _h : int;
		private var _w : int;
		
		private var _raster : Bitmap;
		
		private var _smallRaster : Bitmap;
		
		public var container : Sprite;
		
		
		
		//_____________________________________________________________________________
		//																		 redraw
		private function handleRedraw ( flag : Boolean ) : void {
			if( flag ) {
				//_smallRaster.bitmapData.lock();
				//container.addEventListener( RenderEvent.REDRAW, onRedrawCall );
			} else {
				container.removeEventListener( RenderEvent.REDRAW, onRedrawCall );
				
			}
		}

		private function onRedrawCall (event : RenderEvent) : void {
			var invScale : Number = 1 / Consts.SCALE_FX;
			var zone : Rectangle = event.zone;
			
			var t : DisplayObject = event.target as DisplayObject;
			var matrix : Matrix =  new Matrix( Consts.SCALE_FX, 0, 0, Consts.SCALE_FX, zone.x, zone.y );
			
			//matrix.translate(- _w * ( 1 - invScale ) / 2,- _h * ( 1 - invScale ) / 2 );	
			//matrix.scale( Consts.SCALE_FX, Consts.SCALE_FX );
			
			
			//trace( t.transform.concatenatedMatrix );
			//			_smallRaster.bitmapData.draw( container, matrix, _raster.transform.colorTransform, null, zone, false );
			_smallRaster.bitmapData.draw( t , matrix, _raster.transform.colorTransform, null, zone, false );
			_smallRaster.bitmapData.applyFilter(_smallRaster.bitmapData, zone, zone.topLeft, new BlurFilter( 2,2,1 ) );
			_smallRaster.bitmapData.unlock( zone );
		}
	}
}
